import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.event.MouseInputListener;


public class PokerGUI implements Observer {
	
	private PokerTable table;
	
	public PokerGUI(PokerTable table) {
		this.table = table;
	}
	
	private JFrame frame;
	private JPanel panel_1;
	private JPanel panel_2;
	private JPanel panel_3;
	private JPanel panel_4;
	private JPanel panel_5;
	private JPanel panel_6;
	private JPanel panel_7;
	private JPanel panel_8;
	private JPanel panel_9;
	private JPanel panel_10;
	private JLabel lblWins;
	private JLabel lblLosses;
	
	private ImageIcon cardBack = new ImageIcon("resources/cards/BACK.gif");
	private JLabel dealerCards[];
	private JLabel playerCards[];

	private JButton btnDiscard;

	private JLabel lblDeck;
	private JLabel lblPlayerResults;
	private JLabel lblDealerResults;
	
	/**
	 * Create the applet.
	 * @wbp.parser.entryPoint
	 */
	public void setupGUI() {
		
		frame = new JFrame("Kat's Poker Game");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800, 400);
		frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
		
		JPanel panel = new JPanel();
		panel.setPreferredSize(new Dimension(600, 400));
		frame.getContentPane().add(panel);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		panel_2 = new JPanel();
		panel.add(panel_2);
		panel_2.setLayout(new BorderLayout(0, 0));
		
		panel_3 = new JPanel();
		panel_2.add(panel_3, BorderLayout.NORTH);
		panel_3.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		panel_8 = new JPanel();
		panel_2.add(panel_8, BorderLayout.CENTER);
		
		lblDealerResults = new JLabel("<HTML><BR>");
		panel_8.add(lblDealerResults);
		
		panel_1 = new JPanel();
		panel.add(panel_1);
		panel_1.setLayout(new BorderLayout(0, 0));
		
		panel_4 = new JPanel();
		panel_1.add(panel_4, BorderLayout.NORTH);
		
		panel_5 = new JPanel();
		panel_1.add(panel_5, BorderLayout.CENTER);
		panel_5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		btnDiscard = new JButton("Discard");
		panel_5.add(btnDiscard);
		
		panel_9 = new JPanel();
		panel_1.add(panel_9, BorderLayout.SOUTH);
		
		lblPlayerResults = new JLabel("<HTML><BR>");
		panel_9.add(lblPlayerResults);
		
		panel_6 = new JPanel();
		panel_6.setPreferredSize(new Dimension(150, 400));
		frame.getContentPane().add(panel_6);
		panel_6.setLayout(new BorderLayout(0, 0));
		
		panel_7 = new JPanel();
		panel_6.add(panel_7, BorderLayout.CENTER);
		panel_7.setLayout(new BorderLayout(0, 0));
		
		lblDeck = new JLabel("Click Deck to Deal", cardBack, JLabel.CENTER);
		lblDeck.setVerticalTextPosition(JLabel.BOTTOM);
		lblDeck.setHorizontalTextPosition(JLabel.CENTER);
		
		panel_7.add(lblDeck, BorderLayout.CENTER);
		lblDeck.setHorizontalAlignment(SwingConstants.LEFT);
		
		panel_10 = new JPanel();
		panel_7.add(panel_10, BorderLayout.SOUTH);
		panel_10.setLayout(new BorderLayout(0, 0));
		
		lblWins = new JLabel("Wins: 0");
		panel_10.add(lblWins, BorderLayout.NORTH);
		
		lblLosses = new JLabel("Losses: 0");
		panel_10.add(lblLosses);
		
		dealerCards = new JLabel[5];
		playerCards = new JLabel[5];
		
		frame.pack();
		frame.setVisible(true);
	}
	
	public void setup() {
		
		for (int i = 0; i < 5; i++) {
			dealerCards[i] = new JLabel();
			dealerCards[i].setPreferredSize(new Dimension(73, 97));
			dealerCards[i].setBorder(BorderFactory.createLineBorder(Color.black));
			panel_3.add(dealerCards[i]);
		}
		
		for (int i = 0; i < 5; i++) {
			playerCards[i] = new JLabel();
			playerCards[i].setPreferredSize(new Dimension(73, 97));
			playerCards[i].setBorder(BorderFactory.createLineBorder(Color.black));
			playerCards[i].addMouseListener(new CardListener(i));
			panel_4.add(playerCards[i]);
		}
		
		lblDeck.addMouseListener(new DeckListener());
		
		btnDiscard.addMouseListener(new DiscardListener());
	}

	boolean aDiscardPile[] = new boolean[5];
	boolean discardsAllowed = false;
	
	// Initially there are no discards selected
	public void initializeDiscards() {
		
		for (int i = 0; i < 5; i++) {
			aDiscardPile[i] = false;
		}
		
		discardsAllowed = true;
	}
	
	// Highlight and add to discard pile
	public void select(int index) {
		
		playerCards[index].setBorder(BorderFactory.createLineBorder(Color.blue, 3));
		aDiscardPile[index] = true;
	}
	
	public void deselect(int index) {
		
		playerCards[index].setBorder(BorderFactory.createEmptyBorder());
		aDiscardPile[index] = false;
	}
	
	// Return true if the card is highlighted for discard
	public boolean isSelected(int index) {
		
		if (aDiscardPile[index]) {
			return true;
		}
		
		return false;
	}
	
	public void disableDiscards() {
		
		discardsAllowed = false;
	}
	
	class CardListener implements MouseInputListener {
		
		int index = 0;
		
		public CardListener(int index) {
			this.index = index;
		}
		
		public void mouseClicked(MouseEvent evt) {
			
			if (discardsAllowed) {
			
				if (isSelected(index)) {
					deselect(index);
				}
			
				else {
					select(index);
				}
			}
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseDragged(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseMoved(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	}
	
	class DiscardListener implements MouseInputListener {
		
		public void mouseClicked(MouseEvent evt) {
			
			if (discardsAllowed) {

				disableDiscards();
				table.cardSwap(aDiscardPile);
			}
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseDragged(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseMoved(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}
	}
	
	class DeckListener implements MouseInputListener {
		
		public void mouseClicked(MouseEvent evt) {
			initializeDiscards();
			updateDealer();
			table.playGame(1);
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseDragged(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseMoved(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	}
	
	public void updateDealer() {
		
		for (int i = 0; i < 5; i++) {
			dealerCards[i].setBorder(BorderFactory.createEmptyBorder());
			dealerCards[i].setIcon(cardBack);
		}
	}
	
	public void revealDealer(List<Card> hand) {
		for (int i = 0; i < hand.size(); i++) {
			dealerCards[i].setIcon(hand.get(i).getCardImage());
		}
	}
	
	public void updatePlayer(List<Card> hand) {
		
		for (int i = 0; i < hand.size(); i++) {
			playerCards[i].setBorder(BorderFactory.createEmptyBorder());
			playerCards[i].setIcon(hand.get(i).getCardImage());
		}
	}
	
	public void updateWinsAndLosses() {
		lblWins.setText("Wins: " + table.getPlayerWins());
		lblLosses.setText("Losses: " + table.getDealerWins());
	}
	
	public void resetBoard() {
		
		lblPlayerResults.setText("<HTML><BR>");
		lblDealerResults.setText("<HTML><BR>");
		for (int i = 0; i < 5; i++) {
			playerCards[i].setBorder(BorderFactory.createLineBorder(Color.black));
			dealerCards[i].setBorder(BorderFactory.createLineBorder(Color.black));
			dealerCards[i].setIcon(null);
			playerCards[i].setIcon(null);
		}
	}
	
	@Override
	public void update(Observable ob, Object obj) {
		
		// Update the player's card display
		updatePlayer(table.getPlayer().getHand());
		
		// Display in writing the player's hand value
		lblPlayerResults.setText("<HTML>" + table.getPlayerHand() + "<BR>" + "High card: " + table.getPlayerHighCard());
		
		// Round is over
		if (table.roundComplete()) {
			
			// Pop up the dealer's discard number
			JOptionPane.showMessageDialog(null, "Dealer swapped out " + table.getSwapResults() + " cards.");
			
			// Flip over the dealer's hand
			revealDealer(table.getDealer().getHand());
			
			// Display in writing the dealer's hand value
			lblDealerResults.setText("<HTML>" + table.getDealerHand() + "<BR>" + "High card: " + table.getDealerHighCard());
			
			// Pop up the winner
			JOptionPane.showMessageDialog(null, table.getWinner());
			
			updateWinsAndLosses();
			
			resetBoard();
		}
	}

}
